package diningphilosophers;

import java.util.LinkedList;

public class DiningPhilosophers {

    private int EATINGTIME = 2;
    private int preEmptyTime = 1;
    private int currentTime;
    private LinkedList<Philosopher> p;
    private Fork[] f;
    private LinkedList<Philosopher> eatingPhilosophers;
    String[] nomes = {"Teresa", "Alfredo", "Teobaldo", "Gisleide", "Alberdina", "Cleoneide", "Benolinio", "Godolfredo"};

    public DiningPhilosophers(int numberOfPhilosophers) {
        currentTime = 0;
        p = new LinkedList<Philosopher>();
        f = new Fork[numberOfPhilosophers];

        // Add forks
        for (int a = 0; a < numberOfPhilosophers; a++) {
            f[a] = new Fork();
        }
        for (int a = 0; a < numberOfPhilosophers; a++) {
            if (a == numberOfPhilosophers - 1) {
                p.add(new Philosopher(nomes[a], f[a], f[0], EATINGTIME)); // Round queue
            } else {
                p.add(new Philosopher(nomes[a], f[a], f[a + 1], EATINGTIME)); // Current and next fork
            }
        }
        eatingPhilosophers = new LinkedList<Philosopher>();
    }

    public void runSingleStep() {
        if (p.isEmpty()) {
            return;
        }
        currentTime++;
        if (eatingPhilosophers.isEmpty()) { // First time
            // Step 2 by 2 and make philosophers eat
            for (int a = 0; a < p.size(); a += 2) {
                System.out.println("Eating time: Philosopher " + p.get(a).getName() + " is " + (p.get(a).eat() ? "" : "not ") + "eating");
                eatingPhilosophers.add(p.get(a));
            }
        } else {
            if (currentTime % preEmptyTime == 0) {
                // Makes all philosophers stop eating
                int length = eatingPhilosophers.size();
                for (int a = 0; a < eatingPhilosophers.size(); a++) {
                    eatingPhilosophers.get(a).stopEating();
                    System.out.println("Eating time: Philosopher " + eatingPhilosophers.get(a).getName() + " time ends");
                }
                // Another philosophers can eat
                for (int a = 0; a < p.size(); a++) {
                    if (!eatingPhilosophers.contains(p.get(a))) {
                        if (p.get(a).eat()) {
                            System.out.println("Philosopher " + p.get(a).getName() + " starts eating");
                            eatingPhilosophers.add(p.get(a));
                        }
                    }
                }
                // Remover older occurences
                for (int c = 0; c < length; c++) {
                    eatingPhilosophers.remove();
                }
            }
        }
        for (int a = 0; a < p.size(); a++) {
            if (p.get(a).getTimeLeft() <= 0) {
                System.out.println("Philosopher " + p.get(a).getName() + " ends");
                if (eatingPhilosophers.contains(p.get(a))) {
                    eatingPhilosophers.remove(p.get(a));
                }
                p.remove(a);
            }
        }
    }
}
